import datetime, time
import json
import socket
from threading import currentThread, Thread
from tdr import *


def log_file(log_str):
    str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
    log_filename = '%s_server.log' % str_dt2
    with open(log_filename, 'a', encoding='utf-8') as my_logfile:
        log_str = '%s %s' %(str_dt, log_str)
        my_logfile.write(log_str + '\n')

class HandlerThread(object):
    queue = []  # sockect 队列

    def __init__(self, sock):
        self.sock = sock

    def recv(self):
        data = self.sock.recv(1024)
        return data.decode('utf-8')

    def send(self, data):
        self.sock.sendall(('\n[System]: %s\n' % data).encode('utf-8'))


    # 向队列中广播消息
    def broadcast(self, data):
        for sock in self.queue:
            print('发送给 %s 的数据：%s' % (sock, data))
            sock.sendall('receive_data=%s' % data)

    # 关闭客户端连接
    def stop(self):
        self.send('ByeBye!')
        self.sock.close()
        self.queue.remove(self.sock)  # 关闭连接后，记得从队列中删除

    # 程序入口
    def handler(self):
        thname = currentThread().getName()
        if self.sock not in self.queue:
            self.queue.append(self.sock)
            print('[%s] Got connection from %s' % (thname, self.sock.getpeername()))
            log_file('[%s] Got connection from %s' % (thname, self.sock.getpeername()))
        while True:
            # self.print_with_dt('在 HandlerThread.handle 中循环开始（空等待）...')
            # log_file('在 HandlerThread.handle 中循环开始（空等待）...')
            # try:
            #     self.print_with_dt('queue in Thread: %s' % self.queue)
            #     log_file('queue in Thread: %s' % self.queue)
            #         # self.send('hello')
            #         # data = self.recv()
            # except:  # 如果这里不捕获一下，就无法正常断开客户端连接
            #     self.print_with_dt('%s 断开连接！' % self.sock)
            #     log_file('%s 断开连接！' % self.sock)
            #     self.stop()
            # self.print_with_dt('在 HandlerThread.handle 中循环结束...')
            # log_file('在 HandlerThread.handle 中循环结束，准备sleep(0.1)...')
            time.sleep(0.1)    

    @staticmethod
    def callback_senddata(receive_data):
        now = datetime.datetime.now()
        dt = now.strftime("%Y-%m-%d %H:%M:%S")
        # print('%s 回调函数触发！收到数据：%s' % (dt, receive_data))
        log_file('%s 回调函数触发！收到数据：%s' % (dt, receive_data))
        if HandlerThread.queue:
            # print('%s in Thread.callback_senddata: 队列不为空，开始处理数据.' % dt)
            log_file('%s in Thread.callback_senddata: 队列不为空，开始处理数据.' % dt)
            if receive_data:
                if 'event_type' in receive_data:
                    if receive_data['event_type'] in [RECEIVE_SUCCES, RECEIVE_ERROR, SUBSCRIBE_SUCCESS, SUBSCRIBE_FAIL]:
                        send_data = json.dumps(receive_data).encode('utf-8')
                        for sock in HandlerThread.queue:
                            # print('%s 发送给 %s 的数据：%s' % (dt, sock, send_data))
                            log_file('%s 发送给 %s 的数据：%s' % (dt, sock, send_data))
                            try:
                                sock.sendall(send_data)
                            except:
                                HandlerThread.queue.remove(sock)
                                log_file('发送数据时 Socket 出错！%s 连接异常，在队列中删除！更新后当前队列为：%s' % (sock, HandlerThread.queue))
                            else:
                                log_file('数据发送成功！')    
            else:
                print('%s 奇怪，回调传送了空数据！！' % dt)
                log_file('%s 奇怪，回调传送了空数据！！' % dt) 
        else:
            # print('%s queue: %s. 队列为空，不处理.' % (dt, HandlerThread.queue))
            log_file('%s queue: %s. 队列为空，不处理.' % (dt, HandlerThread.queue))

    @staticmethod
    def callback_heartbeat(receive_data):
        now = datetime.datetime.now()
        dt = now.strftime("%Y-%m-%d %H:%M:%S")
        # print('%s 回调函数触发！收到数据：%s' % (dt, receive_data))
        # log_file('%s 回调函数触发！收到数据：%s' % (dt, receive_data))
        if HandlerThread.queue:
            # print('%s in Thread.callback_heartbeat: 队列不为空，开始处理数据.' % dt)
            log_file('%s in Thread.callback_heartbeat: 队列不为空，开始处理数据.' % dt)
            if receive_data:
                if 'event_type' in receive_data:
                    if receive_data['event_type'] == HEART_BEAT:
                       send_data = json.dumps(receive_data).encode('utf-8')
                       for sock in HandlerThread.queue:
                            # print('%s 发送心跳信息给 %s：%s' % (dt, sock, send_data))
                            # log_file('%s 发送心跳信息给 %s：%s' % (dt, sock, send_data))
                            try:
                                sock.sendall(send_data)
                            except:
                                HandlerThread.queue.remove(sock)
                                log_file('发送心跳给 %s 时出错！在队列中删除！更新后当前队列为：%s' % (sock, HandlerThread.queue))
                            else:
                                # 听取是否有心跳回复
                                try:
                                    recv_heartbeat = sock.recv(1024)
                                except:
                                    HandlerThread.queue.remove(sock)
                                    log_file('接收心跳确认出错！%s 连接异常，在队列中删除！更新后当前队列为：%s' % (sock, HandlerThread.queue))
                                else:
                                    try:
                                        receive_data = json.loads(recv_heartbeat.decode('utf-8'))
                                    except:
                                        log_file('执行json.loads出错！原始信息是 %s' % recv_heartbeat) 
                                    else:
                                        # 返回订阅请求
                                        if 'event_type' in receive_data:
                                            if receive_data['event_type'] == CALLBACK_CMD:
                                                sCode = receive_data['sCode']
                                                user_input = receive_data['user_input']
                                                sMarket = receive_data['sMarket']
                                                log_file('收到客户端 %s 的订阅请求：%s，客户端当前显示品种为：%s.%s。返回到订阅函数中处理。' % (sock, user_input, sCode, sMarket))
                                                return receive_data
                                            else:
                                                log_file('收到 %s 回复的心跳信息：%s，返回空字典。' % (sock, recv_heartbeat))
                                                return {}
                                        else:
                                            print('%s 奇怪，心跳确认收到了不可识别数据：' % (dt, receive_data))
                                            log_file('%s 奇怪，心跳确认收到了不可识别数据：' % (dt, receive_data))
                                            return {}    
            else:
                print('%s 奇怪，回调传送了空数据！！' % dt)
                log_file('%s 奇怪，回调传送了空数据！！' % dt)
                return {}
        else:
            # print('%s queue: %s. 队列为空，不处理.' % (dt, HandlerThread.queue))
            log_file('%s queue: %s. 队列为空，不处理.' % (dt, HandlerThread.queue))
            return {}


    def print_with_dt(self, print_str):
        now = datetime.datetime.now()
        dt = now.strftime("%Y-%m-%d %H:%M:%S")
        print('%s %s' % (dt, print_str))        

    def log_file(self, log_str):
        str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
        log_filename = '%s_server.log' % str_dt2
        with open(log_filename, 'a', encoding='utf-8') as my_logfile:
            log_str = '%s %s' %(str_dt, log_str)
            my_logfile.write(log_str + '\n')